/*
    $Header: /Windows/Shell/ShellExt.root/ShellExt/src/CCmdStub.cpp 1     08-01-05 0:08 Ken $
    $Log: /Windows/Shell/ShellExt.root/ShellExt/src/CCmdStub.cpp $
 * 
 * 1     08-01-05 0:08 Ken

*/


#include "stdafx.h"
#include "CCmdStub.h"
#include "atlutil.h"

CCmdStub::CCmdStub()
{
    m_bIdl=false;
    m_bPathSync=TRUE;
    m_bChgPathPend=false;
    m_szCurPath[0]=0;

    m_hpipeRd=NULL;
    m_hpipeWt=NULL;
    m_hShlPipeIn=NULL;
    m_hShlPipeOut=NULL;

    m_hRcvThread=NULL;

    m_pCmdWrapWnd=NULL;
    m_pIWebBrowser=NULL;

    m_hCmdProc=NULL;
    m_szFilterStr[0]=0;
}

CCmdStub::~CCmdStub()
{
    if(NULL!=m_hRcvThread){
        TerminateThread(m_hRcvThread, 0);
    }

    if(NULL!=m_hpipeRd){
        CloseHandle(m_hpipeRd);
    }
    if(NULL!=m_hpipeWt){
        CloseHandle(m_hpipeWt);
    }
    if(NULL!=m_hShlPipeIn){
        CloseHandle(m_hShlPipeIn);
    }
    if(NULL!=m_hShlPipeOut){
        CloseHandle(m_hShlPipeOut);
    }

    if(NULL!=m_hCmdProc){
        TerminateProcess(m_hCmdProc, 0);
        CloseHandle(m_hCmdProc);
    }
}

BOOL CCmdStub::Init(CCmdStubWnd* pCmdWrapWnd, IWebBrowser2* pIWebBrowser)
{
    ATLASSERT(NULL!=pCmdWrapWnd);
    m_pCmdWrapWnd=pCmdWrapWnd;
    m_pIWebBrowser=pIWebBrowser;

    USES_CONVERSION;

    const TCHAR* pszCurPaht=NULL;
    CUrl curl;
    if(NULL!=m_pIWebBrowser)
    {
        BSTR bstrLocationURL=NULL;
        if (SUCCEEDED(m_pIWebBrowser->get_LocationURL(&bstrLocationURL)))
        {
            CString cstrCurLoc(bstrLocationURL);
            SysFreeString(bstrLocationURL);
            if(curl.CrackUrl(cstrCurLoc.GetBuffer()))
            {
                DWORD dwFlAttr=GetFileAttributes(curl.GetUrlPath()+1);
                if( (INVALID_FILE_ATTRIBUTES!=dwFlAttr)
                    && (FILE_ATTRIBUTE_DIRECTORY&dwFlAttr) )
                {     // url path is /xxx
                    pszCurPaht=curl.GetUrlPath()+1;
                    _tcscpy_s(m_szCurPath, pszCurPaht);
                }
            }
       }
    }

    //
    // Create the I/O pipes for the shell
    //
    SECURITY_ATTRIBUTES SecurityAttributes;
    SecurityAttributes.nLength = sizeof(SecurityAttributes);
    SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL
    SecurityAttributes.bInheritHandle = TRUE; // Shell will inherit handles
    if( (false==CreatePipe(&m_hpipeRd, &m_hShlPipeOut, &SecurityAttributes, 0))
        || (false==CreatePipe(&m_hShlPipeIn, &m_hpipeWt, &SecurityAttributes, 0)))
    {
        ATLTRACE(TEXT("CreatePipe faild:%d!\r\n"), GetLastError());
        return false;
    }

    //
    // get shell
    //
    TCHAR szShell[MAX_PATH];
    if( !GetEnvironmentVariable(_T("ComSpec"), szShell, MAX_PATH) )
    {
        ATLTRACE(TEXT("Can't get shell name:%d!\r\n"), GetLastError());
        return FALSE;
    }
#ifdef _UNICODE
    _tcscat_s( szShell, _T(" /U") );
#else
    _tcscat_s( szShell, _T(" /A") );
#endif

    //
    // Create shell process
    //
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    si.hStdInput  = m_hShlPipeIn;
    si.hStdOutput = m_hShlPipeOut;
    // to inherit stderr, DuplicateHandle
    DuplicateHandle(GetCurrentProcess(), m_hShlPipeOut,
                                GetCurrentProcess(), &si.hStdError,
                                DUPLICATE_SAME_ACCESS, TRUE, 0);

    PROCESS_INFORMATION ProcessInformation;
    if(!CreateProcess(NULL, szShell, NULL, NULL, TRUE, 0, NULL, pszCurPaht?pszCurPaht: NULL,
                      &si, &ProcessInformation))
    {
        ATLTRACE(TEXT("CreateProcess faild :%d!\r\n"), GetLastError());
        return FALSE;
    }
    CloseHandle(ProcessInformation.hThread);
    m_hCmdProc=ProcessInformation.hProcess;

    // create recive thread
    m_hRcvThread=CreateThread(&SecurityAttributes, 0, RcvFromCmdProc
                                                    , LPVOID(this), NULL, NULL);
    if(NULL==m_hRcvThread)
    {
        ATLTRACE(TEXT("CreateThread faild :%d!\r\n"), GetLastError());
        return FALSE;
    }
    return TRUE;
}

BOOL CCmdStub::Send2Cmd(const BYTE* pInput, DWORD dwSize)
{
    DWORD dwWritten=0;

    // change the idle and first line state
    if(false!=m_bIdl)
    {
        m_bIdl=false;
    }

    WriteFile( m_hpipeWt, pInput, dwSize, &dwWritten, NULL );
    if(dwWritten!=dwSize)
    {
        ATLTRACE(TEXT("Send2Cmd faild:%d!\r\n"), GetLastError());
        TCHAR szBuf[MAX_PATH];
        memcpy(szBuf, pInput, dwSize);
        szBuf[dwSize/sizeof(TCHAR)]=0;
        m_pCmdWrapWnd->AppendOutString(szBuf);
        m_pCmdWrapWnd->AppendOutString( TEXT("\r\n!!!Can't be send command: maybe cmd terminated!!!!\r\n") );
        return FALSE;
    }
    return TRUE;
}


BOOL CCmdStub::SetPathAutoSync(BOOL bSyncOn)
{
    BOOL bret=m_bPathSync;
    m_bPathSync=bSyncOn;
    return bret;
}


void CCmdStub::SetCurPath(TCHAR* pszPath)
{
    if( (0!=_tcsicmp(pszPath, m_szCurPath))
            || (FALSE==PathIsDirectory(pszPath))
            || (':'!=pszPath[1])
            || ('\\'!=pszPath[2]) )
    {
        return;
    }

    _tcscpy_s(m_szCurPath, pszPath);
    // idle, send cd command to cmd.exe
    if(TRUE==m_bIdl)
    {
        ChgCmdDir(m_szCurPath);
    }
    else
    {
        m_bChgPathPend=TRUE;
    }
}


DWORD WINAPI CCmdStub::RcvFromCmdProc(LPVOID pThis)
{
    ((CCmdStub*)pThis)->RcvFromCmd();
    return 0;
}

void CCmdStub::RcvFromCmd()
{
    DWORD dwRead;
    BYTE buf[32*1024];
    TCHAR* ptchar=(TCHAR*)buf;
    TCHAR szNotifyTxt[]=TEXT("\r\n!!!the shell terminated! you should restart this window!!!\r\n");
    while(1)
    {
        if( (!ReadFile( m_hpipeRd, buf, sizeof(buf), &dwRead, NULL) )
                || ( 0==dwRead) )
        {
            ATLTRACE(TEXT("ReadFile faild:%d, maybe the cmd.exe terminate!\r\n"), GetLastError());
            m_pCmdWrapWnd->AppendOutString( szNotifyTxt );
            m_hRcvThread=NULL;
            CloseHandle(m_hCmdProc);
            return;
        }

        ptchar[dwRead/sizeof(TCHAR)] = _T('\0');

        // filter the special string
        if(0==_tcsicmp(m_szFilterStr, ptchar)){
            continue;
        }

        //
        // last line
        // the cmd will transfer a prompt line at the end of each command
        //
        if('>'==ptchar[dwRead/sizeof(TCHAR)-1])
        {
            int idHead=(dwRead/sizeof(TCHAR)>MAX_PATH)? (dwRead/sizeof(TCHAR)-MAX_PATH) : 0;
            for(int i=dwRead/sizeof(TCHAR)-4; i>=idHead; i--)
            {   //-4 "\r\n0"
                if((':'==ptchar[i+1])
                    && ('\\'==ptchar[i+2]) )
                {
                    // change to idle state
                    m_bIdl=TRUE;

                    // save the new cur path
                    TCHAR szBuf[MAX_PATH];
                    _tcscpy_s(szBuf, ptchar+i);
                    szBuf[dwRead/sizeof(TCHAR)-i-1]=0;

                                         //
                    // change directory for pending
                    if(TRUE==m_bChgPathPend)
                    {
                        m_bChgPathPend=FALSE;
                        // save the current dir
                        if(0!=_tcsicmp(m_szCurPath, szBuf))
                        {
                            ChgCmdDir(m_szCurPath);
                        }
                    }
                    else if(0!=_tcsicmp(m_szCurPath, szBuf))
                    {
                        // save the current dir
                        _tcscpy_s(m_szCurPath, szBuf);
                        if( (TRUE==m_bPathSync)
                            && (m_pIWebBrowser!=NULL) )
                        {
                            BSTR bstr;
                            bstr = T2BSTR(m_szCurPath);
                            m_pIWebBrowser->Navigate( bstr, NULL, NULL, NULL, NULL);
                        }
                    }
                    break;
                }
            }

        }

        m_pCmdWrapWnd->AppendOutString( ptchar );
    }
}


void CCmdStub::ChgCmdDir(TCHAR* pDir)
{
    _tcscpy_s(m_szFilterStr, TEXT("X: & cd "));
    m_szFilterStr[0]=pDir[0];
    _tcscat_s(m_szFilterStr, pDir+2);
    _tcscat_s(m_szFilterStr, TEXT("\r\n"));

    Send2Cmd((BYTE*)m_szFilterStr, strlen(m_szFilterStr));

}

CCmdStubWnd::CCmdStubWnd()
{
    m_bInuptTypeChar=false;
    m_dwInputStart=0;
    m_hWnd=NULL;
    m_pcCmd=NULL;


    m_itHis=m_lstszHistory.begin();
}

CCmdStubWnd::~CCmdStubWnd()
{
}

void CCmdStubWnd::AppendOutString(TCHAR* pszOut)
{
    DWORD dwLen=_tcslen(pszOut);
    TCHAR* pszAppend=AppendOutBuf(pszOut, dwLen);

    //
    // insert the string with "bs" replaced
    DWORD dwStartPos=m_dwInputStart-m_dwBSNum;
    if(m_dwInputStart<m_dwBSNum)
    {
        dwStartPos=0;
    }
    SendMessage(m_hWnd, EM_SETSEL, (WPARAM)dwStartPos, (LPARAM)m_dwInputStart);
    SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM)false, (LPARAM)pszAppend);
    m_dwBSNum=0;

    //
    // adjust the "ponters"
    DWORD dwNewInputStart=dwStartPos+dwLen-(pszAppend-pszOut);
    int iMove=dwNewInputStart-m_dwInputStart;
    m_dwInputStart+=iMove;
}

TCHAR* CCmdStubWnd::AppendOutBuf(TCHAR* pOut, DWORD dwLen)
{
    for(DWORD i=0; i<dwLen; i++)
    {
        // "backspace"
        if(0x8==pOut[i])
        {
            if(0==i)
            {
                // the first char is "bs"
                m_dwBSNum++;
                if(dwLen==1)
                {
                    return pOut+1;
                }
                else
                {
                    return AppendOutBuf(pOut+1, dwLen-1);
                }
            }
            else
            {
                // remove the char prev "bs"
                TCHAR* pMoveTo=pOut+i;
                for(int j=i-2; j>=0; j--)
                {
                    pMoveTo[j]=pOut[j];
                }
                return AppendOutBuf(pOut+i, dwLen-i);
            }
        }
        else if(0x0c==pOut[i])
        {
            // cls command responds, clear screen!
            SendMessage(m_hWnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
            SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM)false, (LPARAM)TEXT("\0"));
            m_dwInputStart=0;
            return AppendOutBuf(pOut+i+1, (i!=dwLen)?dwLen-i-1:0);
        }
    }
    return pOut;
}


HWND CCmdStubWnd::CreateCmdStubWnd(HWND hwndParent)
{
    //If the window doesn't exist yet, create it now.
    if(NULL!=m_hWnd){
        return NULL;
    }

    //Can't create a child window without a parent.
    if(!hwndParent){
        return NULL;
    }

    // Create term number combox
    m_hWnd=CreateWindowEx(   0,
                                             WC_EDIT, NULL,
                                             WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_VSCROLL | WS_HSCROLL
                                             | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL,
                                             0, 0, 0, 0,
                                             hwndParent,
                                             (HMENU)1,
                                             (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE),
                                             (LPVOID)this);
    if(NULL==m_hWnd)
    {
        ATLTRACE(TEXT("CreateWindowEx faild!\r\n"));
        return NULL;
    }

    // subclass the edit control
    SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
    m_pfnDefEditProc=(WNDPROC)SetWindowLongPtr(m_hWnd, GWLP_WNDPROC , (LONG)WndProc);
    if(NULL==m_pfnDefEditProc)
    {
        ATLTRACE(TEXT("Subclass edit control faild:%d\r\n"), GetLastError());
        return NULL;
    }

    SendMessage( m_hWnd, EM_SETLIMITTEXT, (WPARAM)-1, 0);
    return m_hWnd;
}

LRESULT CALLBACK CCmdStubWnd::WndProc( HWND hWnd,
                          UINT uMessage,
                          WPARAM wParam,
                          LPARAM lParam)
{
    CCmdStubWnd  *pThis = (CCmdStubWnd*)GetWindowLongPtr(hWnd, GWLP_USERDATA);

    switch (uMessage)
    {
    case WM_SETFOCUS:
        pThis->VOnFocusChange(TRUE);
        break;

     case WM_KILLFOCUS:
        pThis->VOnFocusChange(FALSE);
        break;

//    case WM_NOTIFY:
//    pThis->OnNotify(hWnd, (int)(wParam), (LPNMHDR)(lParam));
//    break;

//    case WM_COMMAND:
//    pThis->OnCommand(hWnd, (int)(wParam), (LPARAM)(lParam));
//    break;

    case WM_KEYDOWN:
        return pThis->VOnKeyDown(hWnd, (WPARAM)(wParam), (LPARAM)(lParam));

    case WM_CHAR:
        return pThis->VOnChar(hWnd, (WPARAM)(wParam), (LPARAM)(lParam));

    case WM_SYSCHAR:
        return pThis->VOnSysChar(hWnd, (WPARAM)(wParam), (LPARAM)(lParam));


    case WM_CLEAR:
    case WM_CUT:
    case WM_PASTE:
        return pThis->VOnClearCutPast( hWnd, uMessage );

    default:
        break;
    }

     return CallWindowProc( pThis->m_pfnDefEditProc
                                        , hWnd, uMessage, wParam, lParam);
}
LRESULT CCmdStubWnd::VOnFocusChange(BOOL fFocus)
{
    if(TRUE==fFocus){
        SetFocus(m_hWnd);
    }

    return 0;
};

LRESULT CCmdStubWnd::VOnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    int iStart, iEnd;

    switch(wParam)
    {
    case VK_LEFT:
        SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&iStart, (LPARAM)&iEnd);
        if( (iStart<=m_dwInputStart)
            || (iEnd<=m_dwInputStart))
        {
            SendMessage(m_hWnd, EM_SETSEL, (WPARAM)m_dwInputStart, (LPARAM)m_dwInputStart);
            return 0;
        }
        break;

    case VK_HOME:
        SendMessage(m_hWnd, EM_SETSEL, (WPARAM)m_dwInputStart, (LPARAM)m_dwInputStart);
        return 0;

    case VK_UP:
        ShowHistory(HISTORY_PREV);
        return 0;
    case VK_DOWN:
        ShowHistory(HISTORY_NEXT);
        return 0;
    case VK_PRIOR:
        ShowHistory(HISTORY_TOP);
        return 0;
    case VK_NEXT:
        ShowHistory(HISTORY_BOTTOM);
        return 0;

    default:
        break;
    }

    return CallWindowProc( m_pfnDefEditProc, hWnd, WM_KEYDOWN, wParam, lParam);
}

LRESULT CCmdStubWnd::VOnChar(HWND hWnd,  WPARAM wParam, LPARAM lParam)
{
    LRESULT hr;

    TCHAR key=(TCHAR)wParam;

    int iStart, iEnd;
    SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&iStart, (LPARAM)&iEnd);

    if( (' '<=key)
        && ('~'>=key) )
    {
        if( (iEnd<=m_dwInputStart)
            || (iStart<=m_dwInputStart))
        {
            SendMessage(m_hWnd, EM_SETSEL, (WPARAM)m_dwInputStart, (LPARAM)m_dwInputStart);
        }
    }


    if(TRUE==m_bInuptTypeChar)
    {
        TCHAR szkey[2];
        szkey[0]=key;
        szkey[1]=0;
        AppendOutString(szkey);
        m_pcCmd->Send2Cmd((BYTE*)&key, sizeof(key));
        return 0;
    }
    else
    {
        // backspace
        if(0x8==key)
        {
            if(iEnd<=m_dwInputStart)
            {
                return 0;
            }
        }
        else if( 0x1b==key)
        {
            // ESC
            RemoveUserInput();
            return 0;
        }
        else if( ('\r'==key)        // endter key
                    || ('\n'==key) )
        {   // ctrl+enter
            // copy the user input
            TCHAR szBuf[MAX_PATH];
            DWORD dwBufLen=sizeof(szBuf)/sizeof(szBuf[0]);
            TCHAR* pszBuf=szBuf;
            BOOL bAllocBuf=false;
            dwBufLen-=2;
            if(false==GetUseInput(pszBuf, &dwBufLen))
            {
                pszBuf=new TCHAR[dwBufLen+1+2];
                bAllocBuf=TRUE;
                GetUseInput(pszBuf, &dwBufLen);
            }

            // remove the user input, for it will be echo back by cmd
            RemoveUserInput();

            // insert to history
            if(0!=dwBufLen)
            {
                m_lstszHistory.push_front (pszBuf);
                ResetHistoryPointer();
            }

            _tcscat(pszBuf, TEXT("\r\n"));
                            // send start xxx
            if('\n'==key)
            {
                m_pcCmd->Send2Cmd((const BYTE*)TEXT("start "), _tcslen(TEXT("start "))*sizeof(TCHAR));
            }
            // send to cmd
            m_pcCmd->Send2Cmd((const BYTE*)pszBuf, (dwBufLen+2)*sizeof(TCHAR));

            if(false!=bAllocBuf)
            {
                delete pszBuf;
            }

            return 0;
        }

        hr=CallWindowProc( m_pfnDefEditProc, hWnd, WM_CHAR, wParam, lParam);

        return hr;
    }
}

LRESULT CCmdStubWnd::VOnSysChar(HWND hWnd,  WPARAM wParam, LPARAM lParam)
{
    TCHAR key=(TCHAR)wParam;

    LRESULT hr=CallWindowProc( m_pfnDefEditProc, hWnd, WM_SYSCHAR, wParam, lParam);

    //
    // endter key
    if('\r'==key)
    {
        // copy the user input
        TCHAR szBuf[MAX_PATH];
        DWORD dwBufLen=sizeof(szBuf)/sizeof(szBuf[0]);
        TCHAR* pszBuf=szBuf;
        BOOL bAllocBuf=false;
        if(false==GetUseInput(pszBuf, &dwBufLen))
        {
            pszBuf=new TCHAR[dwBufLen+1];
            bAllocBuf=TRUE;
            GetUseInput(pszBuf, &dwBufLen);
        }

        // insert to history
        if(0!=dwBufLen)
        {
            m_lstszHistory.push_front (pszBuf);
            ResetHistoryPointer();
        }

        AppendOutString(TEXT("\r\n"));
        if(false==RunAs(pszBuf))
        {
            AppendOutString(TEXT("failed!\r\n"));
        }
        _tcsncpy(pszBuf, m_pcCmd->GetCurDir(), MAX_PATH-2);
        _tcscat(pszBuf, TEXT(">"));
        AppendOutString(pszBuf);

        if(false!=bAllocBuf)
        {
            delete pszBuf;
        }
    }
    return hr;
}

LRESULT CCmdStubWnd::VOnClearCutPast( HWND hWnd, UINT uMessage )
{
    int istart,istop;
    SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&istart, (LPARAM)&istop);
    if( (istart<m_dwInputStart)
        || (istop<m_dwInputStart) )
    {
        return 0;
    }

    return CallWindowProc( m_pfnDefEditProc, hWnd, uMessage, 0, 0);
}

BOOL CCmdStubWnd::GetUseInput(TCHAR* pszInput, DWORD* pdwLen)
{
    HLOCAL hBuffer = (HLOCAL)SendMessage( m_hWnd, EM_GETHANDLE, 0, 0);
    ATLASSERT(hBuffer);
    LPCTSTR pszEditBuf = (LPCTSTR)LocalLock(hBuffer);
    ATLASSERT( pszEditBuf );
    pszEditBuf+=m_dwInputStart;

    DWORD dwInputLen=_tcslen(pszEditBuf);
    if(*pdwLen<=dwInputLen)
    {
        *pdwLen=dwInputLen;
        LocalUnlock( hBuffer );
        return false;
    }
    *pdwLen=dwInputLen;

    // copy the user input
    _tcscpy(pszInput, pszEditBuf);
    LocalUnlock( hBuffer );

    return TRUE;
}

void CCmdStubWnd::RemoveUserInput()
{
    // remove the user input, for it will be echo back by cmd
    SendMessage(m_hWnd, EM_SETSEL, (WPARAM)m_dwInputStart, (LPARAM)-1);
    SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM)false, (LPARAM)TEXT("\0"));
}

void CCmdStubWnd::RePlaceUserInput(TCHAR* pszBuf)
{
    // remove the user input, for it will be echo back by cmd
    SendMessage(m_hWnd, EM_SETSEL, (WPARAM)m_dwInputStart, (LPARAM)-1);
    SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM)false, (LPARAM)pszBuf);
}

void CCmdStubWnd::ShowHistory(enum enHistory enHis)
{
    switch(enHis)
    {
    case HISTORY_PREV:
        if(m_itHis!= m_lstszHistory.begin())
        {
            m_itHis--;
        }
        break;

    case HISTORY_NEXT:
        m_itHis++;
        if(m_itHis == m_lstszHistory.end())
        {
            m_itHis--;
        }
        break;

    case HISTORY_TOP:
        m_itHis = m_lstszHistory.begin();
        break;

    case HISTORY_BOTTOM:
        m_itHis = m_lstszHistory.end();
        m_itHis--;
        break;

    default:
        ATLASSERT(false);
        break;
    }

    if(m_itHis != m_lstszHistory.end())
    {
        RePlaceUserInput((*m_itHis).GetBuffer());
    }
}

BOOL CCmdStubWnd::RunAs(TCHAR* pCmd)
{
     STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    PROCESS_INFORMATION ProcessInformation;
    TCHAR szCmdLine[4096];
    _sntprintf_s(szCmdLine, 4096, TEXT("shterm_runas.exe %s"), pCmd);
    if(!CreateProcess(NULL,  szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL,
                                &si, &ProcessInformation))
    {
        ATLTRACE(TEXT("CreateProcess faild :%d!\r\n"), GetLastError());
        return FALSE;
    }
    CloseHandle(ProcessInformation.hThread);
    CloseHandle(ProcessInformation.hProcess);

   return TRUE;
}
